#ifndef SRC_LTA_H_
#define SRC_LTA_H_

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "src/ltbase.h"

void* lt_Realloc(void* ptr, lt_USize size);
void lt_Free(void* ptr, lt_USize size);
void* lt_Malloc(lt_USize size);

#define lta_InitCap() (8)

#define lta_Append(M_array, M_x)                                               \
    do {                                                                       \
        if ((M_array).len >= (M_array).cap) {                                  \
            (M_array).cap = (M_array).len == 0 ? lta_InitCap()                 \
                                               : (M_array).cap * 2;            \
            (M_array).data = lt_Realloc(                                       \
                (M_array).data, (M_array).cap * sizeof(*(M_array).data));      \
        }                                                                      \
        (M_array).data[(M_array).len] = (M_x);                                 \
        (M_array).len += 1;                                                    \
    } while (0)

#define lta_DeInit(M_array)                                                    \
    do {                                                                       \
        lt_Free((M_array).data, (M_array).cap * sizeof(*(M_array).data));      \
        (M_array).data = NULL;                                                 \
        (M_array).len = 0;                                                     \
        (M_array).cap = 0;                                                     \
    } while (0)

#define lta_ArrayOf(M_Type, M_Name)                                            \
    typedef struct M_Name##_ {                                                 \
        M_Type* data;                                                          \
        lt_USize len;                                                          \
        lt_USize cap;                                                          \
    } M_Name

#define lta_ForEach(M_i, M_array)                                              \
    for (lt_USize M_i = 0; M_i < (M_array).len; ++M_i)

lta_ArrayOf(char const*, lta_Strings);
lta_ArrayOf(char, lta_Chars);

lta_ArrayOf(char const*, lta_StringArr);
lta_ArrayOf(char, lta_CharArr);
lta_ArrayOf(lt_U32, lta_U32Arr);
lta_ArrayOf(lt_U64, lta_U64Arr);

#define ltaa_Append(M_arena, M_array, M_x)                                     \
    do {                                                                       \
        if ((M_array).len >= (M_array).cap) {                                  \
            (M_array).cap = (M_array).len == 0 ? lta_InitCap()                 \
                                               : (M_array).cap * 2;            \
            (M_array).data = ltarena_Realloc(                                  \
                (M_arena), (M_array).data,                                     \
                (M_array).cap * sizeof(*(M_array).data));                      \
        }                                                                      \
        (M_array).data[(M_array).len] = (M_x);                                 \
        (M_array).len += 1;                                                    \
    } while (0)

#define ltaa_DeInit(M_arena, M_array)                                          \
    do {                                                                       \
        ltarena_Free((M_arena), (M_array).data,                                \
                     (M_array).cap * sizeof(*(M_array).data));                 \
        (M_array).data = NULL;                                                 \
        (M_array).len = 0;                                                     \
        (M_array).cap = 0;                                                     \
    } while (0)
#endif
